---
title: Agent Sessions
sidebarTitle: Chat History (Sessions)
description: Learn about Agent sessions and managing conversation history.
keywords: [sessions, chat history, history, agent sessions, multi-turn conversations]
---

When we call `Agent.run()`, it creates a stateless, singular Agent run.

But what if we want to continue this conversation i.e. have a multi-turn conversation? That's where "Sessions" come in. A session is collection of consecutive runs.

In practice, a session is a multi-turn conversation between a user and an Agent. Using a `session_id`, we can connect the conversation history and state across multiple runs.

Here are the core concepts:

- **Session:** A session is collection of consecutive runs like a multi-turn conversation between a user and an Agent. Sessions are identified by a `session_id` and house all runs, metrics, state and other data that belong to the session.
- **Run:** Every interaction (i.e. chat or turn) with an Agent is called a **run**. Runs are identified by a `run_id` and `Agent.run()` creates a new `run_id` when called.
- **Messages:** are the individual messages sent between the model and the Agent. Messages are the communication protocol between the Agent and model.

See [Session Storage](/concepts/agents/storage) for more details on how sessions are stored.

## Single session

Here we have an example where a single run is created with an Agent. A `run_id` is automatically generated, as well as a `session_id` (because we didn't provide one tot yet associated with a user.

```python
from agno.agent import Agent
from agno.models.openai import OpenAIChat

agent = Agent(model=OpenAIChat(id="gpt-5-mini"))

# Run agent and return the response as a variable
response = agent.run("Tell me a 5 second short story about a robot")
print(response.content)
print(response.run_id)
print(response.session_id)
```

## Multi-Turn Sessions

Each user that is interacting with an Agent gets a unique set of sessions and you can have multiple users interacting with the same Agent at the same time.

Set a `user_id` to connect a user to their sessions with the Agent.

In the example below, we set a `session_id` to demo how to have multi-turn conversations with multiple users at the same time.

<Steps>
  <Step title="Multi-user, multi-session example">
    ```python
    from agno.agent import Agent
    from agno.models.openai import OpenAIChat
    from agno.db.sqlite import SqliteDb

    db = SqliteDb(db_file="tmp/data.db")

    agent = Agent(
        model=OpenAIChat(id="gpt-5-mini"),
        db=db,
        add_history_to_context=True,
        num_history_runs=3,
    )

    user_1_id = "user_101"
    user_2_id = "user_102"

    user_1_session_id = "session_101"
    user_2_session_id = "session_102"

    # Start the session with user 1
    agent.print_response(
        "Tell me a 5 second short story about a robot.",
        user_id=user_1_id,
        session_id=user_1_session_id,
    )
    # Continue the session with user 1
    agent.print_response("Now tell me a joke.", user_id=user_1_id, session_id=user_1_session_id)

    # Start the session with user 2
    agent.print_response("Tell me about quantum physics.", user_id=user_2_id, session_id=user_2_session_id)

    # Continue the session with user 2
    agent.print_response("What is the speed of light?", user_id=user_2_id, session_id=user_2_session_id)

    # Ask the agent to give a summary of the conversation, this will use the history from the previous messages (but only for user 1)
    agent.print_response(
        "Give me a summary of our conversation.",
        user_id=user_1_id,
        session_id=user_1_session_id,
    )
    ```

  </Step>
  <Step title="Run the example">
    Install libraries

    ```shell
    pip install agno openai
    ```

    Export your key
    ```shell
    export OPENAI_API_KEY=xxx
    ```

    Run the example

    ```shell
    python multi_user_multi_session.py
    ```

  </Step>
</Steps>

<Note>
  For session history and management, you need to have a database assigned to
  the agent. See [Storage](/concepts/db/overview) for more details.
</Note>

### History in Context

As in the example above, we can add the history of the conversation to the context using `add_history_to_context`. You can specify this parameter on the `Agent` or on the `run()` method.

```python
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.in_memory import InMemoryDb

agent = Agent(model=OpenAIChat(id="gpt-5-mini"), db=InMemoryDb())

agent.print_response("Hi, I'm John. Nice to meet you!")

agent.print_response("What is my name?", add_history_to_context=True)
```

Learn more in the [Context Engineering](/concepts/agents/context) documentation.

## Session Summaries

The Agent can store a condensed representations of the session, useful when chat histories gets too long. This is called a "Session Summary" in Agno.

To enable session summaries, set `enable_session_summaries=True` on the `Agent`.

<Steps>
  <Step title="Session summary example">
    ```python session_summary.py
    from agno.agent import Agent
    from agno.models.google.gemini import Gemini
    from agno.db.sqlite import SqliteDb

    db = SqliteDb(db_file="tmp/data.db")

    user_id = "jon_hamm@example.com"
    session_id = "1001"

    agent = Agent(
        model=Gemini(id="gemini-2.0-flash-exp"),
        db=db,
        enable_session_summaries=True,
    )

    agent.print_response(
        "What can you tell me about quantum computing?",
        stream=True,
        user_id=user_id,
        session_id=session_id,
    )

    agent.print_response(
        "I would also like to know about LLMs?",
        stream=True,
        user_id=user_id,
        session_id=session_id
    )

    session_summary = agent.get_session_summary(session_id=session_id)
    print(f"Session summary: {session_summary.summary}")
    ```

  </Step>

  <Step title="Run the example">
    Install libraries

    ```shell
    pip install google-genai agno
    ```

    Export your key
    ```shell
    export GOOGLE_API_KEY=xxx
    ```

    Run the example

    ```shell
    python session_summary.py
    ```

  </Step>
</Steps>

### Customize Session Summaries

You can adjust the session summaries by providing a custom `session_summary_prompt` to the `Agent`.

The `SessionSummaryManager` class is responsible for handling the model used to create and update session summaries.
You can adjust it to personalize how summaries are created and updated:

```python
from agno.agent import Agent
from agno.session import SessionSummaryManager
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb

# Setup your database
db = SqliteDb(db_file="agno.db")

# Setup your Session Summary Manager, to adjust how summaries are created
session_summary_manager = SessionSummaryManager(
    # Select the model used for session summary creation and updates. If not specified, the agent's model is used by default.
    model=OpenAIChat(id="gpt-5-mini"),
    # You can also overwrite the prompt used for session summary creation
    session_summary_prompt="Create a very succinct summary of the following conversation:",
)

# Now provide the adjusted Memory Manager to your Agent
agent = Agent(
    db=db,
    session_summary_manager=session_summary_manager,
    enable_session_summaries=True,
)
```

See the [Session Summary Manager](/reference/session/summary_manager) reference for more details.

## Session history

Agents with storage enabled automatically have access to the message and run history of the session.

You can access these messages using:

- `agent.get_messages_for_session()` -> Gets access to all the messages for the session, for the current agent.
- `agent.get_chat_history()` -> Gets access to all the unique messages for the session.

We can give the Agent access to the chat history in the following ways:

- We can set `add_history_to_context=True` and `num_history_runs=5` to add the messages from the last 5 runs automatically to every message sent to the agent.
- We can be more granular about how many messages to add to include in the list sent to the model, by setting `num_history_messages`.
- We can set `read_chat_history=True` to provide a `get_chat_history()` tool to your agent allowing it to read any message in the entire chat history.
- **We recommend setting all 3: `add_history_to_context=True`, `num_history_runs=3` and `read_chat_history=True` for the best experience.**
- We can also set `read_tool_call_history=True` to provide a `get_tool_call_history()` tool to your agent allowing it to read tool calls in reverse chronological order.

Take a look at this example:

<Steps>
  <Step title="Session history example">
    ```python session_history.py
    from agno.agent import Agent
    from agno.models.google.gemini import Gemini
    from agno.db.sqlite import SqliteDb

    agent = Agent(
        model=Gemini(id="gemini-2.0-flash-exp"),
        db=SqliteDb(db_file="tmp/data.db"),
        add_history_to_context=True,
        num_history_runs=3,
        read_chat_history=True,
        description="You are a helpful assistant that always responds in a polite, upbeat and positive manner.",
    )

    agent.print_response("Share a 2 sentence horror story", stream=True)

    agent.print_response("What was my first message?", stream=True)
    ```

  </Step>
  <Step title="Run the example">
    Install libraries

    ```shell
    pip install google-genai agno
    ```

    Export your key
    ```shell
    export GOOGLE_API_KEY=xxx
    ```

    Run the example

    ```shell
    python session_history.py
    ```

  </Step>
</Steps>

### Search the session history

In some scenarios, you might want to fetch messages from across multiple sessions to provide context or continuity in conversations.

To enable fetching messages from the last N sessions, you need to use the following flags:

- `search_session_history`: Set this to `True` to allow searching through previous sessions.
- `num_history_sessions`: Specify the number of past sessions to include in the search. In the example below, it is set to `2` to include only the last 2 sessions.

It's advisable to keep this number low (2 or 3), as a larger number might fill up the context length of the model, potentially leading to performance issues.

Here's an example of searching through the last 2 sessions:

```python
# Remove the tmp db file before running the script
import os

from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.db.sqlite import SqliteDb

os.remove("tmp/data.db")

db = SqliteDb(db_file="tmp/data.db")

agent = Agent(
    model=OpenAIChat(id="gpt-5-mini"),
    user_id="user_1",
    db=db,
    search_session_history=True,  # allow searching previous sessions
    num_history_sessions=2,  # only include the last 2 sessions in the search to avoid context length issues
)

session_1_id = "session_1_id"
session_2_id = "session_2_id"
session_3_id = "session_3_id"
session_4_id = "session_4_id"
session_5_id = "session_5_id"

agent.print_response("What is the capital of South Africa?", session_id=session_1_id)
agent.print_response("What is the capital of China?", session_id=session_2_id)
agent.print_response("What is the capital of France?", session_id=session_3_id)
agent.print_response("What is the capital of Japan?", session_id=session_4_id)
agent.print_response(
    "What did I discuss in my previous conversations?", session_id=session_5_id
)  # It should only include the last 2 sessions
```

## Control what gets stored in the session

As your sessions grow, you may want to decide what data exactly is persisted. Agno provides three flags to optimize storage while maintaining full functionality during execution:

- **`store_media`** - Controls storage of images, videos, audio, and files
- **`store_tool_messages`** - Controls storage of tool requests and their results
- **`store_history_messages`** - Controls storage of history messages

<Tip>
### How it works

These flags only affect what gets **persisted to the database**. During execution, all data remains available to your agent - media, tool results, and history are still accessible in the `RunOutput` object. The data is scrubbed right before saving to the database.

This means:
- Your agent functionality remains unchanged
- Tools can access all data they need during execution
- Only the database storage is optimized
</Tip>

<Warning>
**Important considerations when using `store_tool_messages=False`:**

- **Tool message pairs are removed together**: To maintain valid message sequences, when tool messages are removed from storage, the corresponding assistant messages that contains tool calls for that tool message are also removed. Most model providers require a strict "tool call pair"

- **Metrics will still consider the tokens spent on the deleted messages**: Your run metrics will still reflect the **actual tokens used during execution**, including the tool calls and results.
</Warning>

### Usage example

```python
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.duckduckgo import DuckDuckGoTools
from agno.db.sqlite import SqliteDb

agent = Agent(
    model=OpenAIChat(id="gpt-4o"),
    tools=[DuckDuckGoTools()],
    db=SqliteDb(db_file="tmp/agents.db"),
    add_history_to_context=True,
    num_history_runs=5,
    store_media=False,              # Don't store images/videos/audio/files
    store_tool_messages=False,       # Don't store tool execution details
    store_history_messages=False,   # Don't store history messages
)

agent.print_response("Search for the latest AI news and summarize it")
```

See more examples in [Disable Storing History Messages](/examples/concepts/agent/session/09_disable_storing_history_messages) and [Disable Storing Tool Messages](/examples/concepts/agent/session/10_disable_storing_tool_messages).

## Developer Resources

- View the [Agent schema](/reference/agents/agent)
- View the [Session schema](/reference/agents/session)
- View [Cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/agents/session/)
